#include "imgutil.h"

#include <cctype>

#include <fstream>

#include <boost/lexical_cast.hpp>
#include <boost/gil.hpp>
#include <boost/gil/extension/io/png.hpp>
#include <boost/property_tree/xml_parser.hpp>

#include "fs.h"


namespace imgutil
{

static Size imgSizeForPng(const std::string &path) {
    namespace g = boost::gil;
    const auto info = g::read_image_info(path, g::png_tag{});
    return Size(static_cast<Size::Width>(info._info._width), static_cast<Size::Height>(info._info._height));
}

static bool isPureInteger(const std::string &s) {
    for (char c : s) {
        if (!std::isdigit(c)) {
            return false;
        }
    }
    return true;
}

static Size imgSizeForSvg(const std::string &path) {
    std::ifstream ifs(path);
    boost::property_tree::ptree tree;
    boost::property_tree::xml_parser::read_xml(ifs, tree);

    const auto attrnode = tree.get_child_optional("svg.<xmlattr>");
    if (!attrnode) {
        return Size::null();
    }
    const auto width = attrnode->get_optional<std::string>("width");
    if (!width || !isPureInteger(*width)) {
        return Size::null();
    }
    const auto height = attrnode->get_optional<std::string>("height");
    if (!height || !isPureInteger(*height)) {
        return Size::null();
    }
    return Size(boost::lexical_cast<Size::Width>(*width), boost::lexical_cast<Size::Height>(*height));
}

Size imgSize(const fs::path &path) {
    const std::string ext = path.extension().generic_string();
    const std::string pathstr = path.generic_string();
    if (ext == ".png") {
        return imgSizeForPng(pathstr);
    }

    if (ext == ".svg") {
        return imgSizeForSvg(pathstr);
    }

    return Size::null();
}

} // namespace imgutil

